/**
 * @description
 * @author yintongwu
 * 2016-9-23 上午11:17:58
 */
package com.xinlan.imageeditlibrary.editimage.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;

public class ImageUntils {
	/**
	 * @descript 二值化+抖动处理+蛇尾扫描  处理
	 * @param BufferedImage
	 * @param 十六进制RGB  black(黑色) 0x00000000  
	 * @param 十六进制RGB  white(白色) 0x00FFFFFF  
	 * @return BufferedImage
	 */
	public Bitmap binaryJitter(Bitmap bufferedImage,int black,int white) throws IOException {
		int height = bufferedImage.getHeight();
		int width = bufferedImage.getWidth();
		int error;
		// 灰度化
		int[][] gray = new int[width][height];
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				int argb = bufferedImage.getPixel(x, y);
				int r = (argb >> 16) & 0xFF;
				int g = (argb >> 8) & 0xFF;
				int b = (argb >> 0) & 0xFF;
				int grayPixel = getCloseColor(b, g, r);
				gray[x][y] = grayPixel;
			}
		}
		// 二值化+抖动算法+蛇尾扫描
		int threshold = ostu(gray, width, height);
		Bitmap binaryBufferedImage = Bitmap.createBitmap(width, height, Config.ARGB_8888);
		for (int x = 1; x < width; x++) {
			if(x%2==1){
				for (int y = 0; y < height; y++) {

					if(gray[x][y] > threshold){
						error = gray[x][y] - 255;  
						gray[x][y] |= white;  //255; // 新值为白色
					} else {
						error = gray[x][y] - 0;  
						gray[x][y] &= black;  //0; // 新值为黑色
					}
					// 如果不是边界
					if(y>1&&y < height-2){
						//向右传播
						gray[x][y+1] &= (int)(gray[x][y+1] + error * 32/134);
						gray[x][y+2] &= (int)(gray[x][y+2] + error * 12/134);
						if(gray[x][y+1] > 255){
							gray[x][y+1] |= white;
						}
					}
					// 如果不是边界
					if(x < width-2){
						// 向下传播
						gray[x+1][y] &= (int)(gray[x+1][y] + error * 32/134);
						gray[x+2][y] &= (int)(gray[x+2][y] + error * 12/134);
						if(y>1&&y< height-2 ){
							// 向右下、左下传播
							gray[x+1][y+1] &= (int)(gray[x+1][y+1] + error * 12/134);
							gray[x+1][y+2] &= (int)(gray[x+1][y+2] + error * 5/134);
							gray[x+2][y+1] &= (int)(gray[x+2][y+1] + error * 5/134);
							gray[x+2][y+2] &= (int)(gray[x+2][y+2] + error * 1/134);
							gray[x+1][y-1] &= (int)(gray[x+1][y-1] + error * 12/134);
							gray[x+1][y-2] &= (int)(gray[x+1][y-2] + error * 5/134);
							gray[x+2][y-1] &= (int)(gray[x+2][y-1] + error * 5/134);
							gray[x+2][y-2] &= (int)(gray[x+2][y-2] + error * 1/134);
						}
					}
					binaryBufferedImage.setPixel(x, y, gray[x][y]);
				}
			}else{
				for (int y= height-1;y>=0;y--) {
					if(gray[x][y] > threshold){
						error = gray[x][y] - 255;  
						gray[x][y] |= white;  //255; // 新值为白色
					} else {
						error = gray[x][y] - 0;  
						gray[x][y] &= black;  //0; // 新值为黑色
					}
					// 如果不是边界
					if(y>1&&y < height-2){
						//向右传播
						gray[x][y+1] &= (int)(gray[x][y+1] + error * 32/134);
						gray[x][y+2] &= (int)(gray[x][y+2] + error * 12/134);
						if(gray[x][y+1] > 255){
							gray[x][y+1] |= white;
						}
					}
					// 如果不是边界
					if(x < width-2){
						// 向下传播
						gray[x+1][y] &= (int)(gray[x+1][y] + error * 32/134);
						gray[x+2][y] &= (int)(gray[x+2][y] + error * 12/134);
						if(y>1&&y< height-2 ){
							// 向右下、左下传播
							gray[x+1][y+1] &= (int)(gray[x+1][y+1] + error * 12/134);
							gray[x+1][y+2] &= (int)(gray[x+1][y+2] + error * 5/134);
							gray[x+2][y+1] &= (int)(gray[x+2][y+1] + error * 5/134);
							gray[x+2][y+2] &= (int)(gray[x+2][y+2] + error * 1/134);
							gray[x+1][y-1] &= (int)(gray[x+1][y-1] + error * 12/134);
							gray[x+1][y-2] &= (int)(gray[x+1][y-2] + error * 5/134);
							gray[x+2][y-1] &= (int)(gray[x+2][y-1] + error * 5/134);
							gray[x+2][y-2] &= (int)(gray[x+2][y-2] + error * 1/134);
						}
					}
					binaryBufferedImage.setPixel(x, y, gray[x][y]);
				}
			}
		}
		return binaryBufferedImage;
	}
	
		

	public int clamp(int val) {
		val = val < 0 ? 0 : val;
		val = val > 255 ? 255 : val;
		return val;
	}

	private int getCloseColor(int b, int g, int r) {
		int a = (int) ((b * 29 + g * 150 + r * 77 + 128) >> 8);
		return a;
	}
	public int[] getStartColor() {  
        return new int[]{246,53,138};  
    }  
      
    public int[] getEndColor() {  
        return new int[]{0,255,255};  
    } 
    
	/**
	 * byte数组到16进制字符串
	 */
	public String byte2string(byte[] data) {
		if (data == null || data.length <= 1)
			return "0x";
		if (data.length > 200000)
			return "0x";
		StringBuffer sb = new StringBuffer();
		int buf[] = new int[data.length];
		// byte数组转化成十进制
		for (int k = 0; k < data.length; k++) {
			buf[k] = data[k] < 0 ? (data[k] + 256) : (data[k]);
		}
		// 十进制转化成十六进制
		for (int k = 0; k < buf.length; k++) {
			if (buf[k] < 16)
				sb.append("0" + Integer.toHexString(buf[k]));
			else
				sb.append(Integer.toHexString(buf[k]));
		}
		return "0x" + sb.toString().toUpperCase();
	}

	/**
	 * 16进制转二进制
	 */
	public String hexString2binaryString(String hexString) {
		if (hexString == null || hexString.length() % 2 != 0)
			return null;
		String bString = "", tmp;
		for (int i = 0; i < hexString.length(); i++) {
			tmp = "0000"
					+ Integer.toBinaryString(Integer.parseInt(
							hexString.substring(i, i + 1), 16));
			bString += tmp.substring(tmp.length() - 4);
		}
		return bString;
	}

	/**
	 * 二进制转16进制
	 */
	public String binaryString2hexString(String bString) {
		if (bString == null || bString.equals("") || bString.length() % 8 != 0)
			return null;
		StringBuffer tmp = new StringBuffer();
		int iTmp = 0;
		for (int i = 0; i < bString.length(); i += 4) {
			iTmp = 0;
			for (int j = 0; j < 4; j++) {
				iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1);
			}
			tmp.append(Integer.toHexString(iTmp));
		}
		return tmp.toString();
	}
	/** 
     * 将byte[]转为各种进制的字符串 
     * @param bytes byte[] 
     * @param radix 基数可以转换进制的范围，从Character.MIN_RADIX到Character.MAX_RADIX，超出范围后变为10进制 
     * @return 转换后的字符串 
     */  
    public String binary(byte[] bytes, int radix){  
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数  
    } 

	public int ostu(int[][] gray, int w, int h) {
		int[] histData = new int[w * h];
		// Calculate histogram
		for (int x = 0; x < w; x++) {
			for (int y = 0; y < h; y++) {
				int red = 0xFF & gray[x][y];
				histData[red]++;
			}
		}

		// Total number of pixels
		int total = w * h;

		float sum = 0;
		for (int t = 0; t < 256; t++)
			sum += t * histData[t];

		float sumB = 0;
		int wB = 0;
		int wF = 0;

		float varMax = 0;
		int threshold = 0;

		for (int t = 0; t < 256; t++) {
			wB += histData[t]; // Weight Background
			if (wB == 0)
				continue;

			wF = total - wB; // Weight Foreground
			if (wF == 0)
				break;

			sumB += (float) (t * histData[t]);

			float mB = sumB / wB; // Mean Background
			float mF = (sum - sumB) / wF; // Mean Foreground

			// Calculate Between Class Variance
			float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);

			// Check if new maximum found
			if (varBetween > varMax) {
				varMax = varBetween;
				threshold = t;
			}
		}

		return threshold;
	}

	public static Bitmap getBitmapByPath(String filePath, BitmapFactory.Options opts) {
		FileInputStream fis = null;
		Bitmap bitmap =null; 
		try { 
			File file = new File(filePath);
			fis = new FileInputStream(file);
			bitmap = BitmapFactory.decodeStream(fis,null,opts);
		} catch (Exception e) {  
		} finally{
			try {
				fis.close();
			} catch (Exception e) {}
		}
		return bitmap;
	}
	
	
}
